// package com.example.everying.service.content.impl;

// import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
// import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// import com.example.everying.mapper.content.ActivityArticleMapper;
// import com.example.everying.mapper.content.ActivityThumbMapper;
// import com.example.everying.model.entity.content.ActivityArticle;
// import com.example.everying.model.entity.content.ActivityThumb;
// import com.example.everying.model.vo.content.ActivityArticleVo;
// import com.example.everying.service.content.ActivityThumbService;
// import lombok.extern.slf4j.Slf4j;
// import org.springframework.beans.factory.annotation.Autowired;
// import org.springframework.dao.DataAccessException;
// import org.springframework.data.redis.core.RedisOperations;
// import org.springframework.data.redis.core.RedisTemplate;
// import org.springframework.data.redis.core.SessionCallback;
// import org.springframework.scheduling.annotation.Async;
// import org.springframework.stereotype.Service;
// import org.springframework.transaction.annotation.Transactional;

// import java.time.LocalDateTime;
// import java.util.HashMap;
// import java.util.List;
// import java.util.Set;
// import java.util.stream.Collectors;
// import java.util.Map;
// /**
//  * @program: everything
//  * @description: 文章点赞实现层
//  * @author: zw
//  * @create: 2025-05-22 15:27
//  **/
// @Service
// @Slf4j
// public class ActivityThumbServiceImpl  extends ServiceImpl<ActivityThumbMapper, ActivityThumb> implements ActivityThumbService {

//     private static final String ARTICLE_LIKES_KEY = "article:likes:%s";
//     private static final String ARTICLE_LIKES_COUNT_KEY = "article:likes:count:%s";
//     private static final String PENDING_SYNC_KEY = "article:likes:pending";

//     @Autowired
//     private RedisTemplate<String, Object> redisTemplate;

//     @Autowired
//     private ActivityArticleMapper articleMapper;


//     @Override
//     public boolean likeArticle(String articleId, String userId) {
//         String articleLikesKey = String.format(ARTICLE_LIKES_KEY, articleId);
//         String likesCountKey = String.format(ARTICLE_LIKES_COUNT_KEY, articleId);

//         // 使用 Redis 事务保证操作原子性
//         redisTemplate.execute(new SessionCallback<Object>() {
//             @Override
//             public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
//                 operations.multi();
//                 // 添加用户到点赞集合
//                 operations.opsForSet().add((K) articleLikesKey, (V) userId);
//                 // 点赞数加1
//                 operations.opsForValue().increment((K) likesCountKey, 1);
//                 // 将文章ID添加到待同步集合
//                 operations.opsForSet().add((K) PENDING_SYNC_KEY, (V) articleId);
//                 return operations.exec();
//             }
//         });

//         return true;
//     }

//     @Override
//     public boolean unlikeArticle(String articleId, String userId) {
//         String articleLikesKey = String.format(ARTICLE_LIKES_KEY, articleId);
//         String likesCountKey = String.format(ARTICLE_LIKES_COUNT_KEY, articleId);

//         // 使用 Redis 事务保证操作原子性
//         redisTemplate.execute(new SessionCallback<Object>() {
//             @Override
//             public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
//                 operations.multi();
//                 // 从点赞集合中移除用户
//                 operations.opsForSet().remove((K) articleLikesKey, (V) userId);
//                 // 点赞数减1
//                 operations.opsForValue().decrement((K) likesCountKey, 1);
//                 // 将文章ID添加到待同步集合
//                 operations.opsForSet().add((K) PENDING_SYNC_KEY, (V) articleId);
//                 return operations.exec();
//             }
//         });
//         return true;
//     }

//     @Override
//     public boolean hasLiked(String articleId, String userId) {
//         String articleLikesKey = String.format(ARTICLE_LIKES_KEY, articleId);
//         return redisTemplate.opsForSet().isMember(articleLikesKey, userId);
//     }

//     @Override
//     public long getLikesCount(String articleId) {
//         String likesCountKey = String.format(ARTICLE_LIKES_COUNT_KEY, articleId);
//         Object countObj = redisTemplate.opsForValue().get(likesCountKey);
//         return countObj != null ? Long.parseLong(countObj.toString()) : 0;
//     }

//     @Override
//     @Async("asyncExecutor")
//     @Transactional
//     public void syncLikesToDatabase() {
//         String pendingSyncKey = PENDING_SYNC_KEY;

//         // 获取所有待同步的文章ID
//         Set<Object> articleIds = redisTemplate.opsForSet().members(pendingSyncKey);

//         if (articleIds == null || articleIds.isEmpty()) {
//             return;
//         }

//         for (Object articleIdObj : articleIds) {
//             String articleId = articleIdObj.toString();
//             syncArticleLikes(articleId);
//         }
//     }

//     private void syncArticleLikes(String articleId) {
//         String articleLikesKey = String.format(ARTICLE_LIKES_KEY, articleId);
//         String likesCountKey = String.format(ARTICLE_LIKES_COUNT_KEY, articleId);
//         try {
//             // 1. 获取Redis中的点赞用户
//             Set<Object> redisUserIds = redisTemplate.opsForSet().members(articleLikesKey);
//             Set<String> redisUserSet = redisUserIds.stream()
//                     .map(Object::toString)
//                     .collect(Collectors.toSet());

//             // 2. 获取数据库中已有的点赞用户
//             List<ActivityThumb> dbLikes = baseMapper.selectList(
//                     new QueryWrapper<ActivityThumb>().eq("article_id", articleId)
//             );
//             Set<String> dbUserSet = dbLikes.stream()
//                     .map(ActivityThumb::getUserId)
//                     .collect(Collectors.toSet());

//             // 3. 计算需要新增和删除的用户
//             Set<String> addUsers = redisUserSet.stream()
//                     .filter(u -> !dbUserSet.contains(u))
//                     .collect(Collectors.toSet());
//             Set<String> deleteUsers = dbUserSet.stream()
//                     .filter(u -> !redisUserSet.contains(u))
//                     .collect(Collectors.toSet());

//             // 4. 增量更新：删除需要移除的点赞
//             if (!deleteUsers.isEmpty()) {
//                 baseMapper.delete(new QueryWrapper<ActivityThumb>()
//                         .eq("article_id", articleId)
//                         .in("user_id", deleteUsers));
//             }

//             // 5. 增量更新：新增需要添加的点赞
//             if (!addUsers.isEmpty()) {
//                 List<ActivityThumb> newLikes = addUsers.stream().map(userId -> {
//                     ActivityThumb like = new ActivityThumb();
//                     like.setArticleId(articleId);
//                     like.setUserId(userId);
//                     like.setCreateTime(LocalDateTime.now());
//                     like.setUpdateTime(LocalDateTime.now());
//                     return like;
//                 }).collect(Collectors.toList());
//                 baseMapper.insertBatch(newLikes);
//             }

//             // 6. 更新点赞数（复用现有逻辑）
//             Integer count = redisUserSet.size();
//             updateArticleLikesCount(articleId, count);

//             // 7. 从待同步集合中移除
//             redisTemplate.opsForSet().remove(PENDING_SYNC_KEY, articleId);

//         } catch (Exception e) {
//             log.error("同步文章点赞数据失败，文章ID: {}", articleId, e);
//         }
//     }

// //    private void syncArticleLikes(String articleId) {
// //        String articleLikesKey = String.format(ARTICLE_LIKES_KEY, articleId);
// //        String likesCountKey = String.format(ARTICLE_LIKES_COUNT_KEY, articleId);
// //
// //        try {
// //            // 获取文章的点赞用户集合
// //            Set<Object> userIds = redisTemplate.opsForSet().members(articleLikesKey);
// //
// //            // 获取文章点赞数
// //            Object countObj = redisTemplate.opsForValue().get(likesCountKey);
// //            Integer count = countObj != null ? Integer.valueOf(countObj.toString()) : 0;
// //
// //            // 转换用户ID类型
// //            List<ActivityThumb> likes = new ArrayList<>();
// //            for (Object userId : userIds) {
// //                ActivityThumb like = new ActivityThumb();
// //                like.setArticleId(articleId);
// //                like.setUserId(userId.toString());
// //                like.setCreateTime(LocalDateTime.now());
// //                likes.add(like);
// //            }
// //
// //            // 先删除文章现有的点赞记录
// //            deleteByArticleId(articleId);
// //
// //            // 批量插入新的点赞记录
// //            if (!likes.isEmpty()) {
// //                baseMapper.insertBatch(likes);
// //            }
// //
// //            // 更新文章点赞数
// //            updateArticleLikesCount(articleId, count);
// //
// //            // 从待同步集合中移除该文章
// //            redisTemplate.opsForSet().remove(PENDING_SYNC_KEY, articleId);
// //
// //        } catch (Exception e) {
// //            log.error("同步文章点赞数据失败，文章ID: {}", articleId, e);
// //            // 可以考虑添加重试逻辑或其他恢复措施
// //        }
// //    }

// //    private void deleteByArticleId(String articleId) {
// //        QueryWrapper<ActivityThumb> wrapper = new QueryWrapper<>();
// //        wrapper.eq("article_id", articleId);
// //        baseMapper.delete(wrapper);
// //    }

//     private void updateArticleLikesCount(String articleId, Integer count) {
//         log.info("准备更新文章点赞数，articleId: {}, count: {}", articleId, count);
//         // 根据 id 查询现有记录
//         LambdaUpdateWrapper<ActivityArticle> wrapper = new LambdaUpdateWrapper<>();
//         wrapper.eq(ActivityArticle::getId, articleId)
//                 .set(ActivityArticle::getThumbs, count);

//         articleMapper.update(null, wrapper);
//         log.info("更新文章点赞数完成，articleId: {}, count: {}", articleId, count);
//     }

//     /**
//      * 文章点赞列表查询
//      * @param userId
//      * @return
//      */
//     @Override
//     public List<ActivityArticleVo> getUserLikes(String userId) {
//         return baseMapper.selectUserId(userId);
//     }
//     @Override
// public Map<String, Boolean> batchHasLiked(List<String> articleIds, String userId) {
//     Map<String, Boolean> result = new HashMap<>();
    
//     if (articleIds == null || articleIds.isEmpty()) {
//         return result;
//     }
    
//     // 使用管道操作提高Redis性能
//     List<Object> results = redisTemplate.executePipelined(new SessionCallback<Object>() {
//         @Override
//         public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
//             for (String articleId : articleIds) {
//                 String articleLikesKey = String.format(ARTICLE_LIKES_KEY, articleId);
//                 operations.opsForSet().isMember((K) articleLikesKey, (V) userId);
//             }
//             return null;
//         }
//     });
    
//     // 组装结果
//     for (int i = 0; i < articleIds.size(); i++) {
//         result.put(articleIds.get(i), (Boolean) results.get(i));
//     }
    
//     return result;
// }

// @Override
// public Map<String, Long> batchGetLikesCount(List<String> articleIds) {
//     Map<String, Long> result = new HashMap<>();
    
//     if (articleIds == null || articleIds.isEmpty()) {
//         return result;
//     }
    
//     // 使用管道操作提高Redis性能
//     List<Object> results = redisTemplate.executePipelined(new SessionCallback<Object>() {
//         @Override
//         public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
//             for (String articleId : articleIds) {
//                 String likesCountKey = String.format(ARTICLE_LIKES_COUNT_KEY, articleId);
//                 operations.opsForValue().get((K) likesCountKey);
//             }
//             return null;
//         }
//     });
    
//     // 组装结果
//     for (int i = 0; i < articleIds.size(); i++) {
//         Object countObj = results.get(i);
//         Long count = countObj != null ? Long.parseLong(countObj.toString()) : 0L;
//         result.put(articleIds.get(i), count);
//     }
    
//     return result;
// }
// }
